package com.jl.card.gp;

import java.security.Key;
import java.util.Arrays;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import com.jl.card.JL;
import com.jl.security.MyCipher;
import com.jl.security.Mac;
import com.jl.security.pad.ISO9797M2;

public class Util {

	public static byte[] tripleDESECB(byte[] key, byte[] data,
			boolean isPaddingISO9797M2) {
		String alg = "DESede/ECB/";
		if (isPaddingISO9797M2) {
			alg += "ISO9797M2";
		} else {
			alg += "NoPadding";
		}
		return MyCipher.encrypt(alg, key, data, null);
	}

	public static byte[] tripleDES_MAC(byte[] key, byte[] data, byte[] iv) {
		return Mac.sign(JL.MAC8_DES_ISO9797_M2, key, data, iv);
	}

	public static byte[] singleDESPlusFinalTripleDES_MAC(byte[] key,
			byte[] data, byte[] icv) {
		byte[] mac = null;
		data = new ISO9797M2().pad(data);
		try {
			Cipher desedeCBCCipher = Cipher.getInstance("DESede/CBC/NoPadding");
			Cipher desCipher = Cipher.getInstance("DES/CBC/NoPadding");
			IvParameterSpec ivSpec = new IvParameterSpec(icv);
			if (data.length % 8 != 0)
				throw new Exception("data block size must be multiple of 8");
			int blocks = data.length / 8;
			Key singledesCMAC = new SecretKeySpec(
					Arrays.copyOfRange(key, 0, 8), "DES");
			for (int i = 0; i < blocks - 1; i++) {
				desCipher.init(Cipher.ENCRYPT_MODE, singledesCMAC, ivSpec);
				byte[] block = desCipher.doFinal(data, i * 8, 8);
				ivSpec = new IvParameterSpec(block);
			}

			int offset = (blocks - 1) * 8;
			Key sessionCMAC = new SecretKeySpec(key, "DESede");
			desedeCBCCipher.init(Cipher.ENCRYPT_MODE, sessionCMAC, ivSpec);
			mac = desedeCBCCipher.doFinal(data, offset, 8);
		} catch (Exception e) {
		}
		return mac;
	}

	public static byte[] tripleDESCBC(byte[] key, byte[] data,
			boolean isPaddingISO9797M2) {
		String alg = "DESede/CBC/";
		if (isPaddingISO9797M2) {
			alg += "ISO9797M2";
		} else {
			alg += "NoPadding";
		}
		return MyCipher.encrypt(alg, key, data, null);
	}

	public static byte[] DESCBC(byte[] key, byte[] data,
			boolean isPaddingISO9797M2) {
		String alg = "DES/CBC/";
		if (isPaddingISO9797M2) {
			alg += "ISO9797M2";
		} else {
			alg += "NoPadding";
		}
		return MyCipher.encrypt(alg, key, data, null);
	}

}
